package com.apes.fn.serveControl.serverChildPackage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.serveControl.serverParentPackage.PControlService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.query.SqlService;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.dingtalk.api.response.CorpReportListResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 外协总控
 * Creator: zouyc
 * CreateDate: 2021-03-12 16:13
 * Description:
 **/
@Service("outAssistControlService")
public class OutAssistControlService  extends PControlService {
    @Autowired
    SqlService sqlService;

    /**
     * 外协需要返回字段
     */
    public static final String[] outGridReturn = {"V_SALE_AMOUNT","V_PRICE_COST","SALE_AMOUNT","PRICE_COST","SALE_INCOME","V_SALE_INCOME","YEAR_RATE","MOUTH_RATE"};

    /**
     * 外协需要返回字段
     */
    public static final String[] topGrid = {"SUPPLIER","SALE_AMOUNT","AMOUNT","LASTAMOUNT","MOUTH_RATE","YEAR_RATE"};

    public static final String[] area2Bar = {"AMOUNT","B_AMOUT","TIME"};
    public static final String[] area2Grid = {"AMOUNT","B_AMOUT"}; //必填字段


    /**
     * 区域1
     * 饼图
     *
     *AMOUNT ：数量
     *CLASS_ID：品类编码
     * CLASS_NAME：品类名称
     *percent：百分比
     * @param re
     * @return
     */
    public JSONArray area1PieChart(SimpleRequest re){
        JSONObject jo = re.getJO();
        com.apestech.framework.json.JSONObject json1 = new com.apestech.framework.json.JSONObject();
        json1.put("DATE_START",returnDate(jo.get("DATE_START")));
        json1.put("DATE_END",returnDate(jo.get("DATE_END")));
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json1.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        super.check(super.returnDate(jo.get("DATE_START")),super.returnDate(jo.get("DATE_END"))); //检测是否有传入时间
        JSONArray array = getObjects(json1, "outAssist.area1PieChart");
        double allSize = array.stream().mapToDouble((item)-> getDouble(item)).sum();
        array.forEach(item ->{
            JSONObject json = (JSONObject)item;
            try {
                json.put("percent",Arith.round(json.getDoubleValue("AMOUNT")/allSize,2));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return array;
    }

    /**
     * 区域1
     * 表格
     *月份：mouth
     *内部外协单金额：SALE_AMOUNT
     * 内部外协单利润:SALE_INCOME
     * 内部外协单成本:PRICE_COST
     * 外采外协单金额：V_SALE_AMOUNT
     * 外采外协单利润:V_SALE_INCOME
     * 外采外协单成本:V_PRICE_COST
     *同比：MOUTH_RATE
     * 环比：YEAR_RATE
     * @param re
     * @return
     */
    public List area1Grid(SimpleRequest re){
        JSONObject jo = re.getJO();
        List returnList = super.checkAndReturnList(MapUtil.mapped(jo));
        initGridDate(returnList,outGridReturn);
        com.apestech.framework.json.JSONObject json1 = new com.apestech.framework.json.JSONObject();
        json1.put("DATE_START",returnDate(jo.get("DATE_START")));
        json1.put("DATE_END",returnDate(jo.get("DATE_END")));
        json1.put("CLASS_ID",jo.get("CLASS_ID"));
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json1.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        //获取指定组数据
        JSONArray array1 = getObjects(json1, "outAssist.area1Grid");
        //获取同比数据
        com.apestech.framework.json.JSONObject json2 = new com.apestech.framework.json.JSONObject(super.obtainMonthErlier(PControlService.tranType(json1)));
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json2.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array2 = getObjects(json2, "outAssist.area1Grid");
        //获取环比数据
        com.apestech.framework.json.JSONObject json3 = new com.apestech.framework.json.JSONObject(super.obtainYearErlier(PControlService.tranType(json1)));
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json3.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array3 = getObjects(json3, "outAssist.area1Grid");
        structAndCombind(returnList, transAndCombind(array1)); //将数据合并到结果集里
        returnList.forEach(item->convertDate((JSONObject)item,mapToList(transAndCombind(array2)),mapToList(transAndCombind(array3)))); //同比数据+一些额外数据整合

        returnList.forEach(item->{
            JSONObject json = (JSONObject)item;
            json.put("V_SALE_AMOUNT",Arith.round(json.getDoubleValue("V_SALE_AMOUNT"),2));
            json.put("V_PRICE_COST",Arith.round(json.getDoubleValue("V_PRICE_COST"),2));
            json.put("SALE_AMOUNT",Arith.round(json.getDoubleValue("SALE_AMOUNT"),2));
            json.put("PRICE_COST",Arith.round(json.getDoubleValue("PRICE_COST"),2));
            json.put("SALE_INCOME",Arith.round(json.getDoubleValue("SALE_INCOME"),2));
            json.put("V_SALE_INCOME",Arith.round(json.getDoubleValue("V_SALE_INCOME"),2));
            json.put("YEAR_RATE",Arith.round(json.getDoubleValue("YEAR_RATE"),2));
            json.put("MOUTH_RATE",Arith.round(json.getDoubleValue("MOUTH_RATE"),2));

        });
        return returnList;
    }

    /**
     * 区域1
     * 柱形图
     * "TOP": 排名
     *"SUPPLIER_ID": 供应商编码
     * "SUPPLIER": 供应商名称
     * "SALE_AMOUNT": 金额
     * "AMOUNT": 数量
     * "LASTAMOUNT": 上月含税金额
     * "MOUTH_RATE": 同比
     * "YEAR_RATE": 环比
     *
     * @param re
     * @return
     */
    public List area1BarChart(SimpleRequest re){
        JSONObject jo = re.getJO();
        com.apestech.framework.json.JSONObject json1 = new com.apestech.framework.json.JSONObject();
        json1.put("DATE_START",returnDate(jo.get("DATE_START")));
        json1.put("DATE_END",returnDate(jo.get("DATE_END")));
        json1.put("CLASS_ID",jo.get("CLASS_ID"));
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json1.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array = tranTypeArray(sqlService.queryId("outAssist.area1BarChart",json1));
        List supplierList = array.stream().map(item->{return ((JSONObject)item).getString("SUPPLIER_ID");}).collect(Collectors.toCollection(ArrayList::new));
        if(array.size() == 0 ) return new ArrayList();

        //获取当前月，该供应商销售金额
        com.apestech.framework.json.JSONObject json2 = new com.apestech.framework.json.JSONObject();
        json2.put("DATE_START",obtainMonthStart());
        json2.put("DATE_END",obtainMonthEnd());
        json2.put("SUPPLIER_ID",supplierList);
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json2.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array2 = getObjects(json2, "outAssist.area1BarChartSupplier");
//
        //获取同比月供应商销售金额
        com.apestech.framework.json.JSONObject json3 = new com.apestech.framework.json.JSONObject(super.obtainMonthErlier(PControlService.tranType(json2)));
        json3.put("SUPPLIER_ID",supplierList);
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json3.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array3 = getObjects(json3, "outAssist.area1BarChartSupplier");
//
//        //获取环比比月供应商销售金额
        com.apestech.framework.json.JSONObject json4 = new com.apestech.framework.json.JSONObject(super.obtainYearErlier(PControlService.tranType(json2)));
        json4.put("SUPPLIER_ID",supplierList);
        if(jo.get("DEPT_ID") != null && jo.getJSONArray("DEPT_ID").size() != 0) json4.put("DEPT_ID",jo.getJSONArray("DEPT_ID").stream().collect(Collectors.toCollection(ArrayList::new)));
        JSONArray array4 = getObjects(json4, "outAssist.area1BarChartSupplier");


        List reList = array.stream().map(item->barGrid((JSONObject) item,array2,array3,array4)).collect(Collectors.toList());
        initTopGridDate(array); //格式化数据，没有的字段填充0

        array.forEach(item->{
            JSONObject iJson = (JSONObject)item;
            iJson.put("SALE_AMOUNT",Arith.round(iJson.getDoubleValue("SALE_AMOUNT"),2));
            iJson.put("LASTAMOUNT",Arith.round(iJson.getDoubleValue("LASTAMOUNT"),2));
            iJson.put("MOUTH_RATE",Arith.round(iJson.getDoubleValue("MOUTH_RATE"),2));
            iJson.put("YEAR_RATE",Arith.round(iJson.getDoubleValue("YEAR_RATE"),2));
        });
        return array;
    }


    /**
     * 区域2图
     * @param re
     * @return
     */
    public List area2Bar(SimpleRequest re){
        JSONObject jo = re.getJO();
        List returnList = super.checkAndReturnList(MapUtil.mapped(jo));
        initGridDate(returnList,area2Bar);
        com.apestech.framework.json.JSONObject json1 = new com.apestech.framework.json.JSONObject();
        json1.put("DATE_START",returnDate(jo.get("DATE_START")));
        json1.put("DATE_END",returnDate(jo.get("DATE_END")));
        JSONArray array = tranTypeArray(sqlService.queryId("outAssist.area2Bar",json1));

        Map map = array.stream().collect(Collectors.groupingBy(item ->{return ((JSONObject)item).getString("MOUTH");}));
        returnList.forEach(item ->{
            JSONObject itemTemp = (JSONObject)item;
            map.forEach((k,v)->{
                List list = (ArrayList)v;
                if(k.equals(itemTemp.getString("mouth"))){

                    Double all = list.stream().mapToDouble(itemAll ->{
                        return ((JSONObject)itemAll).getDoubleValue("AMOUNT");
                    }).sum();

                    Double b_all = list.stream().filter(itemAll->{
                        return ((JSONObject)itemAll).getBoolean("EXPIRED");
                    }).mapToDouble(itemAll ->{
                        return ((JSONObject)itemAll).getDoubleValue("AMOUNT");
                    }).sum();

                    Double time = list.stream().mapToDouble(itemAll ->{
                        return ((JSONObject)itemAll).getDoubleValue("TIME");
                    }).sum();

                    //总单量
                    itemTemp.put("AMOUNT",all);
                    //超时单量
                    itemTemp.put("B_AMOUNT",b_all);
                    //平均耗时
                    itemTemp.put("TIME",time == 0 ? 0 : Arith.round(time/all,2));
                }
            });
        });

        returnList.forEach(item ->{
            JSONObject iJson = (JSONObject)item;
            iJson.put("B_AMOUT",Arith.round(iJson.getDoubleValue("B_AMOUT"),2));
            iJson.put("TIME",Arith.round(iJson.getDoubleValue("TIME"),2));
        });

        return returnList;
    }


    /**
     * 区域2图
     * @param re
     * @return
     */
    public List area2Grid(SimpleRequest re){
        JSONObject jo = re.getJO();
//        List returnList = super.checkAndReturnList(MapUtil.mapped(jo));
//        initGridDate(returnList,area2Grid);
        super.check(returnDate(jo.get("DATE_START")),returnDate(jo.get("DATE_END")));
        com.apestech.framework.json.JSONObject json1 = new com.apestech.framework.json.JSONObject();
        json1.put("DATE_START",returnDate(jo.get("DATE_START")));
        json1.put("DATE_END",returnDate(jo.get("DATE_END")));
        JSONArray array = tranTypeArray(sqlService.queryId("outAssist.area2Grid",json1));


        List reList = new ArrayList();
        //根据员工分组
        Map map = array.stream().collect(Collectors.groupingBy(item ->{return ((JSONObject)item).getString("EXECUTOR_ID");}));
        map.forEach((k,v)->{
            List vList = (ArrayList)v;
            JSONObject reJSON = new JSONObject();
            Double all = vList.stream().mapToDouble(itemAll ->{
                return ((JSONObject)itemAll).getDoubleValue("AMOUNT");
            }).sum();
            Double b_all = vList.stream().filter(itemAll->{
                return ((JSONObject)itemAll).getBoolean("EXPIRED");
            }).mapToDouble(itemAll ->{
                return ((JSONObject)itemAll).getDoubleValue("AMOUNT");
            }).sum();
            Double time = vList.stream().mapToDouble(itemAll ->{
                return ((JSONObject)itemAll).getDoubleValue("TIME");
            }).sum();
            String EXECUTOR_NAME = ((JSONObject)(vList.stream().findFirst().get())).getString("EXECUTOR");
            //总单量
            reJSON.put("AMOUNT",all);
            reJSON.put("L_AMOUNT",all);
            //超时单量
            reJSON.put("B_AMOUNT",b_all);
            reJSON.put("L_B_AMOUNT",b_all);
            //平均耗时
            reJSON.put("TIME",time == 0 ? 0 : Arith.round(time/all,2));
            reJSON.put("L_TIME",time == 0 ? 0 : Arith.round(time/all,2));

            reJSON.put("EXECUTOR_ID",k);
            reJSON.put("EXECUTOR_NAME",EXECUTOR_NAME);
            reList.add(reJSON);
        });
        return reList;
    }

    private Object barGrid(JSONObject item,JSONArray a1,JSONArray a2,JSONArray a3) {
        String  supplier_id = item.getString("SUPPLIER_ID");
        JSONObject a1Json = (JSONObject) a1.stream().filter(itemTemp->{return supplier_id.equals(((JSONObject)itemTemp).getString("SUPPLIER_ID"));}).findFirst().orElse(null);
        JSONObject a2Json = (JSONObject) a2.stream().filter(itemTemp->{return supplier_id.equals(((JSONObject)itemTemp).getString("SUPPLIER_ID"));}).findFirst().orElse(null);
        JSONObject a3Json = (JSONObject) a3.stream().filter(itemTemp->{return supplier_id.equals(((JSONObject)itemTemp).getString("SUPPLIER_ID"));}).findFirst().orElse(null);
        item.put("LASTAMOUNT",a2Json == null ?  0 : a2Json.getDoubleValue("SALE_AMOUNT"));
        item.put("MOUTH_RATE",a2Json == null || a1Json == null || a2Json.getDoubleValue("SALE_AMOUNT") == 0 ? 0:  Arith.round((a1Json.getDoubleValue("SALE_AMOUNT") - a2Json.getDoubleValue("SALE_AMOUNT"))/a2Json.getDoubleValue("SALE_AMOUNT")*100,2));
        item.put("YEAR_RATE",a3Json == null || a1Json == null || a3Json.getDoubleValue("SALE_AMOUNT") == 0 ? 0: Arith.round((a1Json.getDoubleValue("SALE_AMOUNT") - a3Json.getDoubleValue("SALE_AMOUNT"))/a3Json.getDoubleValue("SALE_AMOUNT")*100,2) );
        return item;
    }


    private JSONArray getObjects(com.apestech.framework.json.JSONObject json1, String s) {
        return (JSONArray) Optional.ofNullable(tranTypeArray(sqlService.queryId(s, json1)))
                .orElseGet(() -> new JSONArray());
    }

    private Map transAndCombind(JSONArray array) {
        return array.stream().collect(Collectors.groupingBy(item -> {
            JSONObject json = JSONObject.parseObject(JSON.toJSONString(item));
            return json.getString("DATE_TIME");
        }));
    }

    private List mapToList(Map map){
        List list = new ArrayList();
        map.forEach((k,v)->{
            JSONObject reJson = new JSONObject();
            reJson.put("mouth",k);
            List vArray = (List) v;
            vArray.forEach(vJson ->{
                JSONObject vJsonTemp = (JSONObject)vJson;
                if("WC".equals(vJsonTemp.getString("WCFLAG"))){ //外采
                    reJson.put("V_SALE_AMOUNT",vJsonTemp.getDoubleValue("SALE_AMOUNT"));
                    reJson.put("V_PRICE_COST",vJsonTemp.getDoubleValue("PRICE_COST"));
                }else{//非外采
                    reJson.put("SALE_AMOUNT",vJsonTemp.getDoubleValue("SALE_AMOUNT"));
                    reJson.put("PRICE_COST",vJsonTemp.getDoubleValue("PRICE_COST"));
                }
            });
            list.add(reJson);
        });
        return list;
    }

    /**
     * list和map合并
     * @param returnList
     * @param map
     */
    private void structAndCombind(List returnList, Map map) {
        //合并数据
        returnList.forEach(item->{
            JSONObject itemJson = (JSONObject)item;
            map.forEach((k,v)->{
                if(k.equals(itemJson.getString("mouth"))){
                    List vArray = (List) v;
                    vArray.forEach(vJson ->{
                        JSONObject vJsonTemp = (JSONObject)vJson;
                        if("WC".equals(vJsonTemp.getString("WCFLAG"))){ //外采
                            itemJson.put("V_SALE_AMOUNT",vJsonTemp.getDoubleValue("SALE_AMOUNT"));
                            itemJson.put("V_PRICE_COST",vJsonTemp.getDoubleValue("PRICE_COST"));
                        }else{//非外采
                            itemJson.put("SALE_AMOUNT",vJsonTemp.getDoubleValue("SALE_AMOUNT"));
                            itemJson.put("PRICE_COST",vJsonTemp.getDoubleValue("PRICE_COST"));
                        }
                    });

                }
            });
        });
    }

    /**
     * 初始化数据
     * @param returnList
     */
    private void initGridDate(List returnList,String[] pattern) {
        returnList.forEach(item->{
            JSONObject itemJson = (JSONObject)item;
            for(int i = 0;i<pattern.length;i++){
                if(itemJson.get(pattern[i]) == null) itemJson.put(pattern[i],0);
            }
        });
    }

    /**
     *
     * @param returnList
     */
    private void initTopGridDate(List returnList) {
        returnList.forEach(item->{
            JSONObject itemJson = (JSONObject)item;
            for(int i = 0;i<topGrid.length;i++){
                if((itemJson.get(topGrid[i]) == null || "".equals(itemJson.getString(topGrid[i]).trim())) && "SUPPLIER".equals(topGrid[i])){
                    itemJson.put(topGrid[i],"名称缺失");
                } else if(itemJson.get(topGrid[i]) == null){
                    itemJson.put(topGrid[i],0);
                }
            }
        });
    }

    private void convertDate(JSONObject item, List array1, List array2) {
        //增加定义利润字段
        item.put("V_SALE_INCOME",item.getDoubleValue("V_SALE_AMOUNT") - item.getDoubleValue("V_PRICE_COST"));
        item.put("SALE_INCOME",item.getDoubleValue("SALE_AMOUNT") - item.getDoubleValue("PRICE_COST"));
        //同比
        array1.forEach(aItem->{
            JSONObject aitemJson = (JSONObject)aItem;
            if(aitemJson.getString("mouth").equals(super.obtainMonthErlierDate(item.getString("mouth")))){ //同比数据
                item.put("MOUTH_RATE",Arith.round(((item.getDoubleValue("SALE_AMOUNT") +item.getDoubleValue("V_SALE_AMOUNT")) - (aitemJson.getDoubleValue("SALE_AMOUNT") +aitemJson.getDoubleValue("V_SALE_AMOUNT")))/(aitemJson.getDoubleValue("SALE_AMOUNT") +aitemJson.getDoubleValue("V_SALE_AMOUNT"))*100,2));
            }
        });
        //环比
        array2.forEach(aItem->{
            JSONObject aitemJson = (JSONObject)aItem;

            if(aitemJson.getString("mouth").equals(super.obtainYearErlierDate(item.getString("mouth")))){ //同比数据
                item.put("YEAR_RATE",Arith.round(((item.getDoubleValue("SALE_AMOUNT") +item.getDoubleValue("V_SALE_AMOUNT")) - (aitemJson.getDoubleValue("SALE_AMOUNT") +aitemJson.getDoubleValue("V_SALE_AMOUNT")))/(aitemJson.getDoubleValue("SALE_AMOUNT") +aitemJson.getDoubleValue("V_SALE_AMOUNT"))*100,2));
            }
        });
    }




    private double getDouble(Object item) {
        JSONObject json = JSONObject.parseObject(JSON.toJSONString(item));
        return  json.getDoubleValue("AMOUNT");
    }

    public void Excute(CallAble callAble){
        callAble.Applay();
    }

    @FunctionalInterface
    public interface CallAble{
        void Applay();
    }


//      <if test="SUPPLIER_ID!=null">
//    AND SUPPLIER_ID IN
//            <foreach item="item" collection="SUPPLIER_ID" separator="," open="(" close=")" index="index">
//            #{item}
//                                </foreach>
//                          </if>
}
